/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.deployment.manager;

import br.com.deployment.entidade.registroimovel.GeoRef;
import br.com.deployment.entidade.registroimovel.Imovel;
import br.com.deployment.servico.ImovelServico;
import br.com.deployment.servicoimpl.ImovelServicoImpl;
import br.com.deployment.util.CoordinateConversion;
import br.com.deployment.util.VOGmap;
import br.com.deployment.util.VOGmapIntersection;
import br.com.deployment.utilitario.Msg;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.TopologyException;
import com.vividsolutions.jts.io.ParseException;
import com.vividsolutions.jts.io.WKTReader;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import org.primefaces.event.map.StateChangeEvent;
import org.primefaces.model.map.*;

/**
 *
 * @author roniere
 */
@ManagedBean
@ViewScoped
public class ManagerCoord implements Serializable {

    @EJB
    ImovelServico imovelServico;
    private List<GeoRef> lstGeoRef;
    private MapModel polygonModel;
    private String zoomMap;
    private String zoomMapDialog;
    private String centerMap;
    private String convN;
    private String convE;
    private String convZona;
    private VOGmapIntersection GmapIntersection;
    private MapModel polygonIntesction;
    private VOGmap voGmap;
    private List<VOGmap> listGmap;
    private List<String> lstCor;
    private Integer cont;

    @PostConstruct
    public void init() {

        this.lstGeoRef = new ArrayList<GeoRef>();
        this.polygonModel = new DefaultMapModel();
        this.polygonIntesction = new DefaultMapModel();
        this.centerMap = "-2.9136, -41.7577";
        this.zoomMap = "23";
        initColor();
        listGmap = new ArrayList<VOGmap>();
        voGmap = new VOGmap();
        
    }

    public void onStateChange(StateChangeEvent event) {
        int zoomLevel = event.getZoomLevel();
        zoomMapDialog = String.valueOf(zoomLevel);
    }

    public List<VOGmap> getListGmap() {
        return listGmap;
    }

    public String getZoomMapDialog() {
        return zoomMapDialog;
    }

    public void setZoomMapDialog(String zoomMapDialog) {
        this.zoomMapDialog = zoomMapDialog;
    }

    public void setListGmap(List<VOGmap> listGmap) {
        this.listGmap = listGmap;
    }

    public VOGmap getVoGmap() {
        return voGmap;
    }

    public void setVoGmap(VOGmap voGmap) {
        this.voGmap = voGmap;
    }

    public VOGmapIntersection getGmapIntersection() {
        return GmapIntersection;
    }

    public void setGmapIntersection(VOGmapIntersection GmapIntersection) {
        this.GmapIntersection = GmapIntersection;
    }

    public String getCenterMap() {
        return centerMap;
    }

    public void setCenterMap(String centerMap) {
        this.centerMap = centerMap;
    }

    public String getConvE() {
        return convE;
    }

    public void setConvE(String convE) {
        this.convE = convE;
    }

    public String getConvN() {
        return convN;
    }

    public void setConvN(String convN) {
        this.convN = convN;
    }

    public String getConvZona() {
        return convZona;
    }

    public void setConvZona(String convZona) {
        this.convZona = convZona;
    }

    public List<GeoRef> getLstGeoRef() {
        return lstGeoRef;
    }

    public void setLstGeoRef(List<GeoRef> lstGeoRef) {
        this.lstGeoRef = lstGeoRef;
    }

    public MapModel getPolygonIntesction() {
        return polygonIntesction;
    }

    public void setPolygonIntesction(MapModel polygonIntesction) {
        this.polygonIntesction = polygonIntesction;
    }

    public MapModel getPolygonModel() {
        return polygonModel;
    }

    public void setPolygonModel(MapModel polygonModel) {
        this.polygonModel = polygonModel;
    }

    public String getZoomMap() {
        return zoomMap;
    }

    public void setZoomMap(String zoomMap) {
        this.zoomMap = zoomMap;
    }

    public void removeGeoRef(GeoRef gf) {
        this.lstGeoRef.remove(gf);
        initMap();
    }

    public void initMap() {
        if (lstGeoRef.size() >= 1) {
            polygonModel = new DefaultMapModel();
            Polygon polygon = new Polygon();

            Double centerX = 0D;
            Double centerY = 0D;
            int tam = lstGeoRef.size();
            for (GeoRef geoRef : lstGeoRef) {
                if (geoRef.getLat() != 0.0 && geoRef.getLng() != 0.0) {
                    polygon.getPaths().add(new LatLng(geoRef.getLat(), geoRef.getLng()));
                    polygonModel.addOverlay(new Marker(new LatLng(geoRef.getLat(), geoRef.getLng())));
                    centerX += geoRef.getLat() / tam;
                    centerY += geoRef.getLng() / tam;
                    if(polygon.getPaths().size() == 3){calcArea(polygon);}
                }
            }

            if (tam >= 4 && tam < 6) {
                zoomMap = "18";
            } else if (tam >= 6) {
                zoomMap = "14";
            } else if (tam >= 8) {
                zoomMap = "12";
            }
            centerMap = lstGeoRef.get(0).getLat() + ", " + lstGeoRef.get(0).getLng();

            polygon.setStrokeColor("#FF9900");
            polygon.setFillColor("#FF9900");
            polygon.setStrokeOpacity(0.6);
            polygon.setFillOpacity(0.5);

            polygonModel.addOverlay(polygon);

            for (Marker marker : polygonModel.getMarkers()) {
                marker.setDraggable(true);
            }
        }
    }

    public void converterCoord() {
//        /* EXEMPLO
//        cc.utm2LatLon("24 M 212951 9673551");
//        cc.utm2LatLon("24 M 212951 9673551");
//        */
        String lat = convN;
        String lon = convE;
        String zona = convZona;

        try {
            lat = lat.replace(" ", "");
            lon = lon.replace(" ", "");
            if (zona == null) {
                zona = "M";
            }

            CoordinateConversion cc = new CoordinateConversion();

            String UTM = lon.toString().substring(0, 2) + " " + zona + " " + lon.toString().substring(2) + " " + lat.toString();
            System.err.println("CONVERTENDO COORDENADA: " + UTM);
            lstGeoRef.add(new GeoRef(cc.utm2LatLon(UTM)[0], cc.utm2LatLon(UTM)[1], lon, lat, zona));

        } catch (Exception e) {
            Msg.messagemError("Valores incorretos");
        }

    }

    public void teste() throws ParseException {
        String p1 = "POLYGON ((-7.606060299567146 -44.41115660407986, -7.615358354793988 -44.39703294798029, -7.62220235372107 -44.37877609446505, -7.662008107652762 -44.37051950643254, -7.733295140065195 -44.328921650955785, -7.770094260992261 -44.30063568176405, -7.780268701987419 -44.313804082257235, -7.686461451092123 -44.36993167800232, -7.659006868106722 -44.40549735269305, -7.640473072516129 -44.40747858199689, -7.621987659901308 -44.404752306124564, -7.620236782235469 -44.40964152404157, -7.606060299567146 -44.41115660407986))";
        String p2 = "POLYGON ((-7.659006868106722 -44.40549735269305, -7.686461451092123 -44.36993167800232, -7.780268701987419 -44.313804082257235, -7.792597200538998 -44.32903477306707, -7.738555019497868 -44.34848200186601, -7.729044404378077 -44.38246584544326, -7.72724805980355 -44.38802547176122, -7.726035105699812 -44.398330198681734, -7.659006868106722 -44.40549735269305))";

        WKTReader reader = new WKTReader(new GeometryFactory());

        com.vividsolutions.jts.geom.Polygon polygon =
                (com.vividsolutions.jts.geom.Polygon) reader.read(p1);
        com.vividsolutions.jts.geom.Polygon polygon2 =
                (com.vividsolutions.jts.geom.Polygon) reader.read(p2);

        System.err.println(polygon2.intersects(polygon));
        System.err.println(polygon.touches(polygon2));
        System.err.println(polygon.overlaps(polygon2));

        interseccaoGrilagem(polygon2, false);
        interseccaoGrilagem(polygon, false);

        if (polygon.intersects(polygon2) && !polygon.touches(polygon2)) {
            try {
                interseccaoGrilagem(polygon.intersection(polygon2), true);
            } catch (TopologyException te) {
                System.err.println("ERRO INTER");
            }
        }

        org.primefaces.context.RequestContext.getCurrentInstance().execute("gmapIntesc.show();");
    }

    public void grilagem() {
        cont = 0;
        System.err.println("GRILAGEM");
        List<com.vividsolutions.jts.geom.Polygon> lstPolygon =
                new ArrayList<com.vividsolutions.jts.geom.Polygon>();

        WKTReader reader = new WKTReader(new GeometryFactory());

        for (VOGmap vOGmap : listGmap) {
            String p = "POLYGON((";

            List<GeoRef> lstGf = vOGmap.getGeoref();

            for (GeoRef gf : lstGf) {
                if (gf.getLat() != 0) {
                    p += gf.getLat() + " " + gf.getLng() + ", ";
                }
            }

            p += lstGf.get(0).getLat() + " " + lstGf.get(0).getLng() + " )) ";

            try {
                com.vividsolutions.jts.geom.Polygon polygon =
                        (com.vividsolutions.jts.geom.Polygon) reader.read(p);
                
                lstPolygon.add(polygon);
                
            } catch (ParseException ex) {

                Logger.getLogger(ManagerCoord.class.getName()).log(Level.SEVERE, null, ex);

            }
        }

        System.err.println("GRILAGEM" + lstPolygon);

        if (lstPolygon.size() >= 2) {

            for (com.vividsolutions.jts.geom.Polygon p1 : lstPolygon) {
                System.err.println("polygon p1" + p1);
                interseccaoGrilagem(p1, false);
                cont++;

                for (com.vividsolutions.jts.geom.Polygon p2 : lstPolygon) {
                    System.err.println("polygon p2" + p2);

                    if (p2.compareTo(p1) == -1) {

                        if (p1.intersects(p2) && !p1.touches(p2)) {
                            System.err.println("Cont" + cont);
                            if (p2.contains(p1)) {
                                System.err.println("P2 CONTEM P1");
                                interseccaoGrilagem(p1, false);
                            } else {
                                if (p2.intersects(p1) && !p2.touches(p1)) {
                                    System.err.println("P2 - P1");
                                    interseccaoGrilagem(p2.intersection(p1), true);
                                } else {
                                    System.err.println("P1 - P2");
                                    interseccaoGrilagem(p1.intersection(p2), true);
                                }
                            }
                        }


                    }
                }
            }
        }

        org.primefaces.context.RequestContext.getCurrentInstance().execute("gmapIntesc.show();");
    }

    private void initColor() {
        lstCor = new ArrayList<String>();
        lstCor.add("#FF9900");
        lstCor.add("#2288AA");
        lstCor.add("#8F49FF");
        lstCor.add("#004B84");
        lstCor.add("#FEFF49");
        lstCor.add("#A5FFFF");
        lstCor.add("#A7F477");
        lstCor.add("#7db9e8");
        lstCor.add("#8FAAB5");
        lstCor.add("#3B5998");

        lstCor.add("http://maps.google.com/mapfiles/ms/micons/blue-dot.png");
        lstCor.add("http://maps.google.com/mapfiles/ms/micons/pink-dot.png");
        lstCor.add("http://maps.google.com/mapfiles/ms/micons/yellow-dot.png");

    }

    private String getColor() {
        Random random = new Random();
        return lstCor.get(random.nextInt(10));
    }

    private String getIcon() {
        Random random = new Random();
        int n = 12 - random.nextInt(3);

        return lstCor.get(n);
    }

    public void interseccaoGrilagem(Geometry gmt1, Boolean conflito) {
//        cont++;

        Polygon polygonInte = new Polygon();
        Double x = 0D, y = 0D;

        List<LatLng> path = new ArrayList<LatLng>();

        for (Coordinate c : gmt1.getCoordinates()) {
            path.add(new LatLng(c.x, c.y));
            x += c.x / gmt1.getCoordinates().length;
            y += c.y / gmt1.getCoordinates().length;
        }

        polygonInte.setPaths(path);


        if (!conflito) {
            System.err.println("Número: " + cont + " - " + listGmap.size());

            LatLng coord1 = new LatLng(x, y);
            String cor = getColor();

            VOGmap obj = listGmap.get(1);

            polygonIntesction.addOverlay(new Marker(coord1,
                    obj.getName(), obj.getName(),
                    getIcon()));
            obj.setCor(cor);
            System.err.println("PRINT "+obj.getName() + " cor: "+obj.getCor());
            polygonInte.setStrokeColor(cor);
            polygonInte.setFillColor(cor);
            polygonInte.setStrokeOpacity(0.5);
            polygonInte.setFillOpacity(0.5);

        } else {
            polygonInte.setStrokeColor("#d93c3c");//("#d93c3c");
            polygonInte.setFillColor("#d93c3c");
            polygonInte.setStrokeOpacity(0.8);
            polygonInte.setFillOpacity(0.8);
        }

        polygonIntesction.addOverlay(polygonInte);
        polygonInte = new Polygon();
    }

    public void interseccao2(Geometry gmt1, Geometry gmt2, Geometry gmInt) {
        System.err.println("intesccao");
        Polygon polygonInte = new Polygon();
        Polygon polygonOrig = new Polygon();
        Polygon polygonArea = new Polygon();

        for (Coordinate c : gmt1.getCoordinates()) {
            polygonInte.getPaths().add(new LatLng(c.x, c.y));
        }
        polygonInte.setStrokeColor("#00ff00");
        polygonInte.setFillColor("#00ff00");
        polygonInte.setStrokeOpacity(0.7);
        polygonInte.setFillOpacity(0.7);


        for (Coordinate c : gmt2.getCoordinates()) {
            polygonOrig.getPaths().add(new LatLng(c.x, c.y));
        }

        polygonOrig.setStrokeColor("#d93c3c");
        polygonOrig.setFillColor("#d93c3c");
        polygonOrig.setStrokeOpacity(0.7);
        polygonOrig.setFillOpacity(0.7);



//         for (Coordinate c : gmInt.getCoordinates()) {
//            polygonArea.getPaths().add(new LatLng(c.x, c.y));
//        }

        polygonArea.setStrokeColor("#FF9900");
        polygonArea.setFillColor("#FF9900");
        polygonArea.setStrokeOpacity(0.6);
        polygonArea.setFillOpacity(0.5);

        polygonIntesction.addOverlay(polygonInte);
        polygonIntesction.addOverlay(polygonOrig);
//        polygonIntesction.addOverlay(polygonArea);



    }

    public boolean verificaMap() {
        try {
            WKTReader reader = new WKTReader(new GeometryFactory());
            String p1 = "POLYGON((";

            if (lstGeoRef.size() >= 3) {

                System.err.println("Verifica Map" + lstGeoRef.size());

                for (GeoRef gf : lstGeoRef) {
                    if (gf.getLat() != 0) {
                        p1 += gf.getLat() + " " + gf.getLng() + ", ";
                    }
                    System.err.println("Coordenadas: " + p1.toString());
                }
                p1 += lstGeoRef.get(0).getLat() + " " + lstGeoRef.get(0).getLng() + " )) ";

                com.vividsolutions.jts.geom.Polygon polygon1 =
                        (com.vividsolutions.jts.geom.Polygon) reader.read(p1);

                List<Imovel> lstI = imovelServico.findAll();

                for (Imovel im : lstI) {

                    if (im.getObjeto() != null) {

                        String p2 = "POLYGON((";

                        List<GeoRef> lstGF = im.getObjeto().getGeoReferenciamento();

                        if (lstGF.size() >= 3) {

                            for (GeoRef gf : lstGF) {
                                p2 += gf.getLat() + " " + gf.getLng() + ", ";
                            }

                            p2 += lstGF.get(0).getLat() + " " + lstGF.get(0).getLng() + " ))";

                            com.vividsolutions.jts.geom.Polygon polygon2 = (com.vividsolutions.jts.geom.Polygon) reader.read(p2);

                            if (polygon1.intersects(polygon2)) {
                                if (polygon2.contains(polygon1)) {
                                    interseccao(polygon1, im);
                                }
                                if (polygon1.contains(polygon2)) {
                                    interseccao(polygon2, im);
                                } else {
                                    interseccao(polygon1.intersection(polygon2), im);
                                }

                                return true;
                            }
                        }

                    }
                }
            } else if (lstGeoRef.size() > 1 && lstGeoRef.size() < 3) {
                return true;
            }
        } catch (ParseException ex) {
            Logger.getLogger(ImovelServicoImpl.class.getName()).log(Level.SEVERE, null, ex);
            Msg.messagemError("Erro em geolocalização, verifique as coordenadas1");
        } catch (Exception e) {
            Msg.messagemError("Erro em geolocalização, verifique as coordenadas");
            return true;
        }
        return false;
    }

    public void interseccao(Geometry gmt, Imovel objIm) throws ParseException {

        GmapIntersection = new VOGmapIntersection();
        Polygon polygonInte = new Polygon();
        Polygon orig = new Polygon();
        Polygon imovelConf = new Polygon();

        for (Coordinate c : gmt.getCoordinates()) {
            polygonInte.getPaths().add(new LatLng(c.x, c.y));
        }
        polygonInte.setStrokeColor("#00ff00");
        polygonInte.setFillColor("#00ff00");
        polygonInte.setStrokeOpacity(0.7);
        polygonInte.setFillOpacity(0.7);

        GmapIntersection.setArea(calcArea(polygonInte));
        GmapIntersection.setImovel(objIm);

        for (GeoRef gfi : objIm.getObjeto().getGeoReferenciamento()) {
            imovelConf.getPaths().add(new LatLng(gfi.getLat(), gfi.getLng()));
        }

        imovelConf.setStrokeColor("#d93c3c");
        imovelConf.setFillColor("#d93c3c");
        imovelConf.setStrokeOpacity(0.7);
        imovelConf.setFillOpacity(0.7);

        polygonInte.setStrokeOpacity(0.5);
        polygonInte.setFillOpacity(0.5);


        for (GeoRef gr : lstGeoRef) {
            orig.getPaths().add(new LatLng(gr.getLat(), gr.getLng()));
        }

        orig.setStrokeColor("#FF9900");
        orig.setFillColor("#FF9900");
        orig.setStrokeOpacity(0.6);
        orig.setFillOpacity(0.5);

        polygonIntesction.addOverlay(imovelConf);
        polygonIntesction.addOverlay(orig);
        polygonIntesction.addOverlay(polygonInte);


    }

    public double calcArea(Polygon pl){

        WKTReader reader = new WKTReader(new GeometryFactory());

        String p = "POLYGON(( ";
        for (LatLng ll : pl.getPaths()) {
            p += ll.getLat() + " " + ll.getLng() + ", ";
        }
        p += "" + pl.getPaths().get(0).getLat() + " " + pl.getPaths().get(0).getLng() + " )) ";

        com.vividsolutions.jts.geom.Polygon polygonInt = null;
        try {
            p = "POLYGON ((-2.926926 -41.751338, -2.926977 -41.751242, -2.927116 -41.751365, -2.927060 -41.751454, -2.926926 -41.751338))";
            polygonInt = (com.vividsolutions.jts.geom.Polygon) reader.read(p);
            System.err.println(polygonInt.getArea() + ": Area");
            System.err.println(polygonInt.getLength() + "LENGTH");
            System.err.println(polygonInt.getBoundary());
            System.err.println(polygonInt.getDimension());
        } catch (ParseException ex) {
            Logger.getLogger(ManagerCoord.class.getName()).log(Level.SEVERE, null, ex);
        }
        return polygonInt.getArea();

    }

    public void add() {
        voGmap.setGeoref(lstGeoRef);
        listGmap.add(voGmap);
        voGmap = new VOGmap();
        lstGeoRef = new ArrayList<GeoRef>();
    }
}
